//////////////////////////////////////////////
//                                          //
//          Alexander K. Haley's            //
//      Vector Test Pattern Generator       //
//    (For Prototype Hardware, w/o CPU)     //
//                                          //
//                Build #12                  //
//          Last edit 6/29/2020             //
//        Originally made 4/28/2020         //
//                                          //
//        (c) Alexander K. Haley            //
//                  of                      //
//            Kincaid Arcade                //
//                                          //
//////////////////////////////////////////////

//Porting over to the new Double-Buffered Vector RAM PCB.
//I still need to do all the Address and Data output stuff...


//address pins: a0-a10 = pin 49-42, 53-50
//data pins: q0-q15 = pin 37-30, 22-29
//misc pins:
//  processorready = pin 38
//  processoroverride = pin 39
//  writeenable = pin 40
//  outputenable = pin 41
//  chipselect = pin 50
//  framecomplete = pin 19  INPUT

//gonna need to correct these pins
/*byte azero  = 22;
byte aone   = 23;
byte atwo   = 24;
byte athree = 25;
byte afour  = 26;
byte afive  = 27;
byte asix   = 28;
byte aseven = 29;
byte aeight = 30;
byte anine  = 31;
byte aten   = 32;

//data pins
byte qzero     = 38;
byte qone      = 39;
byte qtwo      = 40;
byte qthree    = 41;
byte qfour     = 42;
byte qfive     = 43;
byte qsix      = 44;
byte qseven    = 45;
byte qeight    = 46;
byte qnine     = 47;
byte qten      = 48;
byte qeleven   = 49;*/
//byte qtwelve   = 50; Technically, they aren't ever used...
//byte qthirteen = 51;
//byte qfourteen = 52;
//byte qfifteen  = 53;

//misc. pins
byte processorready = 38;

byte writeenable    = 40;
byte outputenable   = 41;
byte chipselect     = 50;
byte framecomplete  = 19;

byte processoroverride = 39;

byte TTLINVX = 20;
byte TTLINVY = 21;
//Frame Buffer
//                  1     2    3    4     5     6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56   57   58   59   60   61   62   63   64   65   66   67   68   69   70   71   72   73   74   75   76   77   78   79   80   81   82   83   84   85   86   87   88   89   90   91   92   93   94   95   96
int xcoords[97] = {-96,  -96, 927, 927,  -96,  0,   64,  64,  0,   32,  96,  736, 800, 832, 768, 768, 832, 800, 736, 96,  32,  144, 144, 208, 208, 144, 208, 240, 240, 304, 304, 240, 272, 304, 400, 336, 336, 400, 432, 432, 496, 496, 432, 496, 528, 528, 560, 592, 592, 560, 528, 688, 624, 624, 688, 682, 624, 672, 704, 736, 736, 704, 672, 672, 640, 576, 608, 608, 640, 576, 544, 544, 480, 480, 544, 480, 448, 384, 384, 448, 352, 352, 288, 288, 256, 192, 224, 224, 256, 192, 160, 96,  160, 96,  96,  96};
int ycoords[97] = {-177, 591, 591, -177, -177, 32,  96,  320, 384, 416, 352, 352, 416, 384, 320, 96,  32,  0,   64,  64,  0,   96,  192, 192, 96,  144, 144, 96,  192, 192, 144, 144, 144, 96,  96,  96,  192, 192, 96,  192, 192, 96,  144, 144, 96,  192, 192, 160, 128, 96,  96,  96,  96,  192, 192, 144, 144, 224, 224, 256, 288, 320, 320, 224, 224, 224, 224, 320, 320, 320, 224, 320, 320, 224, 272, 272, 224, 224, 320, 320, 320, 224, 320, 224, 224, 224, 224, 320, 320, 320, 320, 272, 226, 224, 320, 320};
int zvalues[97] = {0,    15,  15,  15,    15,  0,   15,  15,  15,  0,   15,  15,  15,  0,   15,  15,  15,  0,   15,  15,  15,  0,   15,  15,  15,  0,   15,  0,   15,  15,  15,  15,  0,   15,  0,   15,  15,  15,  0,   15,  15,  15,  0,   15,  0,   15,  15,  15,  15,  15,  15,  0,   15,  15,  15,  0,   15,  0,   15,  15,  15,  15,  15,  15,  0,   15,  0,   15,  0,   15,  0,   15,  15,  15,  0,   15,  0,   15,  15,  15,  0,   15,  15,  15,  0,   15,  0,   15,  0,   15,  0,   15,  15,  0,   15,  128};
//I have a couple of negatives to counteract the x+96 and y+304 that happens later in the program.
//z is brightness 0-15 (8th bit of z signals end of frame data)
//a zero for z will have the graphics card "skip" to the location, rather than draw. Anything greater than 128 pauses graphics card.

//variables
int currentaddress  = 1;
int internaladdress = 0;
int mathaddress     = 0;

int currentdata = 0;
int mathdata    = 0;

byte bank = 0;
byte portdata = 0;

byte address[12];
byte data[12];

unsigned long currentmillis = 0;
unsigned long lastmillis = 0;

void setup() {
//The ports on the Mega are weird...
DDRA = DDRA | B11111111;
DDRB = DDRB | B00001111;
DDRC = DDRC | B11111111;
DDRD = DDRD | B10000000;
DDRG = DDRG | B00000111;
DDRL = DDRL | B11111111;

//high speed ain't necessary here, so I'll be lazy... :)
digitalWrite(chipselect,LOW);
digitalWrite(outputenable,HIGH); //Make sure we're in high impedance mode.
digitalWrite(writeenable,HIGH);

digitalWrite(TTLINVX, LOW);
digitalWrite(TTLINVY, LOW);

//load both frame buffers with data
for(int x=0; x<289; x++)
  {
    computeaddress();
    computedata();
    writedata();
    currentaddress++;
  }
initiateprocessoroverride();
currentaddress = 1;
internaladdress = 0;
bank = 0;

for(int x=0; x<289; x++)
  {
    computeaddress();
    computedata();
    writedata();
    currentaddress++;
  }
vgenchecker();
currentaddress = 1;
internaladdress = 0;
bank = 0;
}

void loop() {
  // put your main code here, to run repeatedly:
//toggle active frame buffer each time the vgen sends FRAMECOMPLETE.
while(currentmillis < lastmillis+17)
  {
    currentmillis = millis();  
  }
vgenchecker();
lastmillis = currentmillis;
}

void computeaddress()
{
  //split address into zeros and ones
  mathaddress = currentaddress;  
  portdata = (unsigned int)mathaddress >> 8;
  PORTB = portdata;            //NOTE! This will make pins 10-13 do potentially weird stuff. If you wish to use them, you will need to improve this.
  //get the MSB 8 bits alone
  /*if(mathaddress >= 1024)
    {
      //digitalWrite(aten,HIGH); 
      PORTC = PORTC | B00100000;
      mathaddress -= 1024; 
    }
  else
    {
      //digitalWrite(aten,LOW);
      PORTC = PORTC & B11011111;
    }
    
  if(mathaddress >= 512)
    {
      //digitalWrite(anine,HIGH); 
      PORTC = PORTC | B01000000; 
      mathaddress -= 512; 
    }
  else
    {
      //digitalWrite(anine,LOW);
      PORTC = PORTC & B10111111;
    }
    
  if(mathaddress >= 256)
    {
      //digitalWrite(aeight,HIGH);  
      PORTC = PORTC | B10000000;
      mathaddress -= 256; 
    }
  else
    {
      //digitalWrite(aeight,LOW);
      PORTC = PORTC & B01111111; 
    }
  */
  mathaddress = currentaddress;
  (unsigned int)mathaddress << 8; //get rid of the 8 MSBits
  portdata = (unsigned int)mathdata >> 8;    //move them back into the last 8 bits. Gets the LSB 8 bits alone
  PORTL = portdata;
}

void computedata()
{
  if(bank == 3)
    {
      bank = 0;  
      internaladdress ++;
    }
  
  if(bank == 0) //x bank
    {
      currentdata = xcoords[internaladdress];
      currentdata += 96;
    }
  else if(bank == 1) //y bank
    {
      currentdata = ycoords[internaladdress];
      currentdata += 304;
    }
  else if(bank == 2) //zbank
    {
      currentdata = zvalues[internaladdress];
    }

  //Do the MSB 8 bits
  mathdata = currentdata;
  portdata = (unsigned int)mathdata >> 8;
  PORTA = portdata;
  
  //Do the LSB 8 bits
  mathdata = currentdata;
  (unsigned int)mathdata << 8;
  portdata = (unsigned int)mathdata >> 8;
  PORTC = portdata;
  /*
  if(mathdata >= 2048)
    {
      //digitalWrite(qeleven,HIGH); 
      PORTL = PORTL | B00000001;
      mathdata -= 2048; 
    }
  else
    {
      //digitalWrite(qeleven,LOW);
      PORTL = PORTL & B11111110;
    }

  if(mathdata >= 1024)
    {
      //digitalWrite(qten,HIGH); 
      PORTL = PORTL | B00000010;
      mathdata -= 1024; 
    }
  else
    {
      //digitalWrite(qten,LOW);
      PORTL = PORTL & B11111101;
    }
    
  if(mathdata >= 512)
    {
      //digitalWrite(qnine,HIGH);
      PORTL = PORTL | B00000100;  
      mathdata -= 512; 
    }
  else
    {
      //digitalWrite(qnine,LOW);
      PORTL = PORTL & B11111011;
    }
    
  if(mathdata >= 256)
    {
      //digitalWrite(qeight,HIGH);  
      PORTL = PORTL | B00001000;
      mathdata -= 256; 
    }
  else
    {
      //digitalWrite(qeight,LOW);
      PORTL = PORTL & B11110111;
    }
    
  if(mathdata >= 128)
    {
      //digitalWrite(qseven,HIGH);  
      PORTL = PORTL | B00010000;
      mathdata -= 128; 
    }
  else
    {
      //digitalWrite(qseven,LOW);
      PORTL = PORTL & B11101111;
    }
    
  if(mathdata >= 64)
    {
      //digitalWrite(qsix,HIGH);  
      PORTL = PORTL | B00100000;
      mathdata -= 64; 
    }
  else
    {
      //digitalWrite(qsix,LOW);
      PORTL = PORTL & B11011111;
    }
    
  if(mathdata >= 32)
    {
      //digitalWrite(qfive,HIGH); 
      PORTL = PORTL | B01000000; 
      mathdata -= 32; 
    }
  else
    {
      //digitalWrite(qfive,LOW);
      PORTL = PORTL & B10111111;
    }
    
  if(mathdata >= 16)
    {
      //digitalWrite(qfour,HIGH);  
      PORTL = PORTL | B10000000;
      mathdata -= 16; 
    }
  else
    {
      //digitalWrite(qfour,LOW);
      PORTL = PORTL & B01111111;
    }
    
  if(mathdata >= 8)
    {
      //digitalWrite(qthree,HIGH);  
      PORTG = PORTG | B00000001;
      mathdata -= 8; 
    }
  else
    {
      //digitalWrite(qthree,LOW);
      PORTG = PORTG & B11111110;
    }
    
  if(mathdata >= 4)
    {
      //digitalWrite(qtwo,HIGH); 
      PORTG = PORTG | B00000010; 
      mathdata -= 4; 
    }
  else
    {
      //digitalWrite(qtwo,LOW);
      PORTG = PORTG & B11111101;
    }
    
  if(mathdata >= 2)
    {
      //digitalWrite(qone,HIGH);  
      PORTG = PORTG | B00000100;
      mathdata -= 2; 
    }
  else
    {
      //digitalWrite(qone,LOW);
      PORTG = PORTG & B11111011;
    }
    
  if(mathdata >= 1)
    {
      //digitalWrite(qzero,HIGH);  
      PORTD = PORTD | B10000000;
      mathdata -= 1; 
    }
  else
    {
      //digitalWrite(qzero,LOW);
      PORTD = PORTD & B01111111;
    }

  if(mathdata != 0)
    {
      //digitalWrite(errorled,HIGH);  
    }
  */
}

void writedata()
{
  //set chip select to low, just in case...
  PORTB = PORTB & B11110111;
  //digitalWrite(writeenable,LOW);
  //digitalWrite(writeenable,HIGH);
  PORTG = PORTG & B11111101;
  PORTG = PORTG | B00000010;
  bank ++;
}

void initiateprocessoroverride()
{
  //digitalWrite(processoroverride, HIGH);
  PORTG = PORTG | B00000100;
  //digitalWrite(processorready, HIGH);
  PORTD = PORTD | B10000000;
  //digitalWrite(processoroverride, LOW);
  PORTG = PORTG & B11111011;
  //digitalWrite(processorready, LOW);  
  PORTD = PORTD & B01111111;
}

void vgenchecker()
{
  while(digitalRead(framecomplete) == LOW)
    {
      delayMicroseconds(1);  
    }
  if(digitalRead(framecomplete) == HIGH)
    {
      //digitalWrite(processorready,HIGH);
      PORTD = PORTD | B10000000;
      //digitalWrite(processorready,LOW);
      PORTD = PORTD & B01111111;
    }  
}
